package com.algorithm.arrays;/*
 *@Author:DOWN
 *@Date:2021/12/13 17:30
 *@Comment:泛型数组
 */

import java.util.Objects;

public class Arrays<E> {
    /**
     * 数据空间、长度
     */
    private E[] data;
    private int size;
    @SuppressWarnings("unchecked")
    public Arrays(int capacity) {
        this.data = (E[]) new Object[capacity];
    }
    @SuppressWarnings("unchecked")
    public Arrays(E[] arrs) {
        this.data = (E[]) new Object[arrs.length];
        System.arraycopy(arrs, 0, data, 0, arrs.length);
        size=data.length;
    }

    public Arrays() {
        this(10);
    }


    /**
     * 获取元素个数
     *
     * @return int
     */
    public int getSize() {
        return size;
    }


    /**
     * 根据索引获取元素
     *
     * @param index 索引
     * @return item
     */
    public E get(int index) {
        if (0 > index || index >= size) {
            throw new IllegalArgumentException("index if error!");
        }
        return data[index];
    }

    /**
     * 替换元素
     *
     * @param index      索引
     * @param updateItem 更新的元素
     */
    public void set(int index, E updateItem) {
        if (0 > index || index >= size) {
            throw new IllegalArgumentException("index if error!");
        }
        this.data[index] = updateItem;
    }

    /**
     * 包含校验
     *
     * @param item 元素
     * @return boolean
     */
    public boolean contains(E item) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i].equals(item)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 寻找元素下标
     *
     * @param item 元素
     * @return int
     */
    public int find(E item) {
        for (int i = 0; i < this.size; i++) {
            if (this.data[i].equals(item)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * 移除元素
     *
     * @param index 索引
     * @return boolean
     */
    public E remove(int index) {
        E old = this.data[index];
        if (index >= size) {
            throw new IllegalArgumentException("index if error!");
        }
        if (size - 1 - index >= 0) {
            System.arraycopy(this.data, index + 1, this.data, index, size - 1 - index);
        }
        size--;
        this.data[size] = null;
        if (size == data.length / 4 && data.length / 2 != 0) {
            reSize(data.length / 2);
        }
        return old;
    }

    /**
     * 获取最后一个元素
     *
     * @return item
     */
    public E getLast() {
        return get(size - 1);
    }

    /**
     * 获取第一个元素
     *
     * @return item
     */
    public E getFist() {
        return get(0);
    }

    /**
     * 移除首元素
     *
     * @return boolean
     */
    public E removeFirst() {
        return remove(0);
    }

    /**
     * 移除尾元素
     *
     * @return boolean
     */
    public E removeLast() {
        return remove(this.size - 1);
    }

    /**
     * 获取空间容量
     *
     * @return int
     */
    public int getCapacity() {
        return data.length;
    }

    /**
     * 长度是否为空
     *
     * @return boolean
     */
    public boolean isEmpty() {
        return this.size == 0;
    }

    /**
     * 添加新元素
     *
     * @param newItem 元素
     */
    public void add(E newItem) {
        add(this.size, newItem);
    }

    /**
     * 根据索引位置添加元素
     *
     * @param index   索引
     * @param newItem 元素
     */
    public void add(int index, E newItem) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index if error!");
        }
        if (size == data.length) {
            reSize(size * 2);
        }
        if (size - index >= 0) {
            System.arraycopy(data, index, data, index + 1, size - index);
        }
        this.data[index] = newItem;
        size++;
    }

    /**
     * 动态扩、缩容量
     *
     * @param newCapacity 新的容量
     */
    @SuppressWarnings("unchecked")
    private void reSize(int newCapacity) {
        E[] newArray = (E[]) new Object[newCapacity];
        if (this.size >= 0) {
            System.arraycopy(this.data, 0, newArray, 0, this.size);
        }
        data = newArray;
    }

    public void swap(int one, int two) {
        if (one < 0 || one >= size || two < 0 || two >= size) {
            throw new IllegalArgumentException(" Index is illegal!");
        }
        E t = data[one];
        data[one] = data[two];
        data[two] = t;
    }

    @Override
    public String toString() {
        if (this.data == null) {
            return "null";
        }
        int iMax = this.size - 1;
        if (iMax == -1) {
            return "[]";
        }
        StringBuilder b = new StringBuilder();
        b.append('[');
        for (int i = 0; i < this.size; i++) {
            b.append(this.data[i]);
            if (i == iMax) {
                return b.append(']').toString();
            }
            b.append(", ");
        }
        return b.toString();
    }
}
